package com.funny.stock.base.service;

import com.funny.stock.base.util.PropertiesCopyUtil;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;


public abstract class BaseCrudServiceV2<VO,DO,ID> implements CrudServiceV2<VO,ID> , InitializingBean {

    JpaRepository<DO,ID> baseRepository;

    protected abstract JpaRepository<DO,ID> setupJpaRepository();

    protected abstract Class<DO> getDOClass();

    protected abstract Class<VO> getVOClass();


    protected DO convertDO(VO src){
        return PropertiesCopyUtil.copyProperties(src, getDOClass());
    }

    protected VO convertVO(DO doObj){
        return PropertiesCopyUtil.copyProperties(doObj, getVOClass());
    }

//    protected List<DO> convertDOList(List<VO> src){
//        DO target = null;
//        return (List<DO>) PropertiesCopyUtil.copyPropertiesByList(src, target.getClass());
//    }
//
//    protected List<VO> convertVOList(List<DO> src){
//        VO target = null;
//        return (List<VO>) PropertiesCopyUtil.copyPropertiesByList(src, target.getClass());
//    }

    @Override
    public <S extends VO> S save(S entity) {
        DO convert = convertDO(entity);
        return (S) convertVO(baseRepository.save(convert));
    }

    @Override
    public <S extends VO> List<S> saveAll(List<S> entities) {
        List<DO> list = entities.stream().map(this::convertDO).collect(Collectors.toList());

        List<VO> result = baseRepository.saveAll(list)
                .stream()
                .map(this::convertVO)
                .collect(Collectors.toList());

        return (List<S>) result;
    }

    @Override
    public VO findById(ID id) {
        Optional<DO> obj = baseRepository.findById(id);
        return obj.map(this::convertVO).orElse(null);
    }

    @Override
    public boolean existsById(ID id) {
        return baseRepository.existsById(id);
    }

    @Override
    public List<VO> findAll() {
        return  baseRepository.findAll()
                .stream()
                .map(this::convertVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<VO> findAll(Sort sort) {
        return baseRepository.findAll(sort)
                .stream()
                .map(this::convertVO)
                .collect(Collectors.toList());
    }

    @Override
    public Page<VO> findAll(Pageable pageable) {
        Page<DO> page = baseRepository.findAll(pageable);

        return page.map(this::convertVO);
    }

    @Override
    public List<VO> findAllById(List<ID> ids) {
        List<DO> doList = baseRepository.findAllById(ids);
        return doList.stream().map(this::convertVO)
                .collect(Collectors.toList());
    }

    @Override
    public long count() {
        return baseRepository.count();
    }

    @Override
    public void deleteById(ID id) {
        baseRepository.deleteById(id);
    }

    @Override
    public void delete(VO entity) {
        baseRepository.delete(convertDO(entity));
    }

    @Override
    public void deleteAll(List<? extends VO> entities) {
        List<DO> list = entities.stream().map(this::convertDO).collect(Collectors.toList());

        baseRepository.deleteAll(list);
    }

//    @Override
//    public void deleteAll() {
//        baseRepository.deleteAll();
//    }

    @Override
    public void afterPropertiesSet() throws Exception {
        baseRepository = setupJpaRepository();

    }
}
